﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MetroToolbox.Collections;
using Windows.UI.Xaml;

namespace MetroToolbox.Interactivity
{
    public abstract class AttachableCollection<T> : DependencyObjectCollection<T>, IAttachedObject where T : DependencyObject, IAttachedObject
    {
        public AttachableCollection()
        {
            CollectionChanged += AttachableCollection_CollectionChanged;
        }

        void AttachableCollection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (e.OldItems != null)
            {
                foreach (var o in e.OldItems)
                {
                    if (((T)o).AssociatedObject != null)
                    {
                        ((T)o).Detach();
                    }
                }
            }

            if (e.NewItems != null && AssociatedObject != null)
            {
                foreach (var o in e.NewItems)
                {
                    ((T)o).Attach(AssociatedObject);
                }
            }
        }

        protected DependencyObject AssociatedObject { get; private set; }

        public void Attach(DependencyObject dependencyObject)
        {
            if (dependencyObject != AssociatedObject)
            {
                if (AssociatedObject != null)
                {
                    Detach();
                }

                AssociatedObject = dependencyObject;

                foreach (var o in this)
                {
                    o.Attach(dependencyObject);
                }

                OnAttached();
            }
        }

        public void Detach()
        {
            OnDetaching();

            foreach (var o in this)
            {
                o.Detach();
            }

            AssociatedObject = null;
        }

        protected virtual void OnAttached() { }

        protected virtual void OnDetaching() { }

        DependencyObject IAttachedObject.AssociatedObject { get { return this.AssociatedObject; } }
    }
}
